#include "Parser.h"

using namespace std;
using namespace glm;

Symbol parseGeometry(ifstream &file, Symbol curToken, Scene *scene) {
    Geometry *g;
    if (curToken.t == TSphere) {
        g = new WSphere();
        curToken = g->parse(file, matchToken(file, curToken, TSphere));
    }
    else if (curToken.t == Plane) {
        g = new WPlane();
        curToken = g->parse(file, matchToken(file, curToken, Plane));
    }
    else if (curToken.t == Triangle) {
        g = new WTriangle();
        curToken = g->parse(file, matchToken(file, curToken, Triangle));
    }
    else if (curToken.t == Box) {
        g = new WBox();
        curToken = g->parse(file, matchToken(file, curToken, Box));
    }
    else if (curToken.t == Cone) {
        g = new WCone();
        curToken = g->parse(file, matchToken(file, curToken, Cone));
    }
    else {
        if (curToken.isToken) {
            cout << "Expected Object, found " << 
            tokenList[curToken.t] << endl;
        }
        else {
            cout << "Expected Object, found " << curToken.num << endl;
        }
        exit(1);
    }

    scene->geometry.add(g);
    if (g->finish.lightFinish) {
        scene->lights.add(g);
    }
    return curToken;
}

Symbol parseObject(ifstream& file, Symbol curToken, Scene *scene) {
    if (curToken.t == Camera) {
        WCamera *c = new WCamera();
        curToken = c->parse(file, matchToken(file, curToken, Camera));
        if (scene->camera != NULL) {
            cout << "Cannot define multiple cameras\n";
            exit(1);
        }

        scene->camera = c;
        return curToken;
    }
    else if (curToken.t == Light) {
        WLight *l = new WLight();
        curToken = l->parse(file, matchToken(file, curToken, Light));
        scene->lights.add(l);

        return curToken;
    }
    else {
        curToken = parseGeometry(file, curToken, scene);
        return curToken;
    }
}

Symbol parseStatement(ifstream &file, Symbol curToken, Scene *scene) {
    if (curToken.isToken && curToken.t != Eof) {
        return parseObject(file, curToken, scene);
    }
    else if (curToken.t != Eof) {
        cout << "Expected object, found number: " << curToken.num << endl;
        exit(1);
    }
    else {
        return curToken;
    }
}

Scene *parseScene(ifstream &file) {
    Scene *ret;
    ret = new Scene();
    Symbol curToken = nextToken(file);
    int i = 0;
    while (curToken.t != Eof && file.good()) {
        curToken = parseStatement(file, curToken, ret);
    }

    return ret;
}
